import "../css/style.css";
import "../css/desert.css";
import "../css/smoothness/jquery-ui-1.8.13.custom.css";

let gl = null;      // WebGL 上下文
let prg = null;     // program 着色器
let c_width = 0;    // canvas的宽
let c_height = 0;   // canvas的高

let coneVertexBuffer = null;  // 正方形顶点缓冲区
let coneIndexBuffer = null;   // 正方形索引缓冲区

let indices = [];   // 存储正方形索引的数组
let vertices = [];  // 存储正方形顶点的数组

let vbo_name = 'undefined';
let vbo_size = 0;
let vbo_usage = 0;

let ibo_name = 'undefined';
let ibo_size = 0;
let ibo_usage = 0;

let is_vertices_vbo = '';
let is_coneVertexBuffer_vbo = '';

let mvMatrix = mat4.create();
let pMatrix = mat4.create();

/**
 * 一些操作图形处理器(GPU)的指令
 * 如何处理我们传入的顶点和片元（有关详细信息，请参阅第3章）
 */
function initProgram() {
    let fgShader = utils.getShader(gl, 'shader-fs');
    let vxShader = utils.getShader(gl, 'shader-vs');

    prg = gl.createProgram();
    // 添加一个预先定义的着色器
    gl.attachShader(prg, vxShader);
    gl.attachShader(prg, fgShader);
    gl.linkProgram(prg);

    if (!gl.getProgramParameter(prg, gl.LINK_STATUS)) {
        alert('Could not initialise shaders');
    }

    gl.useProgram(prg);
    //下面代码获取着色器中的uniforms和attributes的引用
    // 这是一个必须的步骤，因为着色器不是用JavaScript编写的，而是用GLSL语言。
    prg.vertexPosition = gl.getAttribLocation(prg, 'aVertexPosition');
    prg.pMatrixUniform = gl.getUniformLocation(prg, 'uPMatrix');
    prg.mvMatrixUniform = gl.getUniformLocation(prg, 'uMVMatrix');
}

/*
    * Creates the buffers that contain the geometry of the square
    *

    */

/**
 *  创建梯形缓冲区
 *
 */
function initBuffers() {

    vertices = [1.5, 0, 0,
        -1.5, 1, 0,
        -1.5, 0.809017, 0.587785,
        -1.5, 0.309017, 0.951057,
        -1.5, -0.309017, 0.951057,
        -1.5, -0.809017, 0.587785,
        -1.5, -1, -4.10207e-010,
        -1.5, -0.809017, -0.587785,
        -1.5, -0.309017, -0.951057,
        -1.5, 0.309017, -0.951057,
        -1.5, 0.809017, -0.587785];

    indices = [0, 1, 2,
        0, 2, 3,
        0, 3, 4,
        0, 4, 5,
        0, 5, 6,
        0, 6, 7,
        0, 7, 8,
        0, 8, 9,
        0, 9, 10,
        0, 10, 1];

    // 顶点缓冲区
    coneVertexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, coneVertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
    gl.bindBuffer(gl.ARRAY_BUFFER, null);

    // 索引缓冲区
    coneIndexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, coneIndexBuffer);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);

    if (coneVertexBuffer === gl.getParameter(gl.ARRAY_BUFFER_BINDING)) {
        vbo_name = "coneVertexBuffer";
    }
    if (coneIndexBuffer === gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING)) {
        ibo_name = "coneIndexBuffer";
    }

    vbo_size = gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE);
    vbo_usage = gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_USAGE);

    ibo_size = gl.getBufferParameter(gl.ELEMENT_ARRAY_BUFFER, gl.BUFFER_SIZE);
    ibo_usage = gl.getBufferParameter(gl.ELEMENT_ARRAY_BUFFER, gl.BUFFER_USAGE);

    //Unbind current VBO and current IBO. Good Practice!
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
    gl.bindBuffer(gl.ARRAY_BUFFER, null);

    //We can call isBuffer at any point (even if there is no buffer bound), because isBuffer only checks on the type of the object
    //i.e. Is the object a WebGL buffer or not.
    try {
        if (gl.isBuffer(vertices)) {
            is_vertices_vbo = "Yes"
        } else {
            is_vertices_vbo = "Invalid"; //isBuffer returns false if the buffer invalidated flag is set
        }
    } catch (e) {
        is_vertices_vbo = "No";
    }
    if (gl.isBuffer(coneVertexBuffer)) {
        is_coneVertexBuffer_vbo = "Yes"
    } else {
        is_coneVertexBuffer_vbo = "No";
    }
}

/**
 * JQuery code to update GUI
 */
function updateInfo() {
    $('#t_vbo_name').html(vbo_name);
    $('#t_ibo_name').html(ibo_name);
    $('#t_vbo_size').html(vbo_size);
    $('#t_vbo_usage').html(vbo_usage);
    $('#t_ibo_size').html(ibo_size);
    $('#t_ibo_usage').html(ibo_usage);
    $('#s_is_vertices_vbo').html(is_vertices_vbo);
    $('#s_is_coneVertexBuffer_vbo').html(is_coneVertexBuffer_vbo);
}

function drawScene() {
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.enable(gl.DEPTH_TEST);

    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    gl.viewport(0, 0, c_width, c_height);

    mat4.perspective(45, c_width / c_height, 0.1, 10000.0, pMatrix);
    mat4.identity(mvMatrix);
    mat4.translate(mvMatrix, [0.0, 0.0, -5.0]);

    gl.uniformMatrix4fv(prg.pMatrixUniform, false, pMatrix);
    gl.uniformMatrix4fv(prg.mvMatrixUniform, false, mvMatrix);

    gl.bindBuffer(gl.ARRAY_BUFFER, coneVertexBuffer);
    gl.vertexAttribPointer(prg.aVertexPosition, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(prg.vertexPositionAttribute);

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, coneIndexBuffer);
    gl.drawElements(gl.LINE_LOOP, indices.length, gl.UNSIGNED_SHORT, 0);
}

function renderLoop() {
    utils.requestAnimFrame(renderLoop);
    drawScene();
}

function runWebGLApp() {
    // console.log(utils);
    gl = utils.getGLContext('canvas-element-id');
    c_width = gl.canvas.width;
    c_height = gl.canvas.height;

    initProgram();

    initBuffers();

    updateInfo();

    renderLoop();
}

runWebGLApp();
